﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Collections;
using System.IO;
using System.Xml;

namespace SharpShare.Storage.ApplePhotoLibrary {
    public sealed class PhotoLibrary {
        public PhotoLibrary() {
            this.Images = new AssetCollection<Image>();
            this.Faces = new AssetCollection<Face>();
        }

        public AssetCollection<Image> Images { get; private set; }
        public AssetCollection<Face> Faces { get; private set; }

        public void Read(IStorageContainer source) {
            IStorageFile albumDataFile = source.Contents["AlbumData.xml"].DemandFile();

            using (Stream stream = new StorageDataStream(albumDataFile.Open(StorageFileAccess.Read, StorageFileAccess.Read))) {
                using (XmlTextReader reader = new XmlTextReader(stream)) {
                    object root = PropertyList.Read(reader);
                    this.Read((IDictionary)root);
                }
            }
        }

        public void Read(IDictionary root) {
            // Read master image list.
            IDictionary masterRoot = (IDictionary)root["Master Image List"];

            this.Images.Clear();

            foreach (DictionaryEntry entry in masterRoot) {
                IDictionary infoRoot = (IDictionary)entry.Value;

                Image image = new Image() {
                    Key = entry.Key.AsString(),
                    Type = infoRoot["MediaType"].AsString().AsEnum<MediaType>() ?? MediaType.Image,
                    Caption = infoRoot["Caption"].AsString(),
                    Comment = infoRoot["Comment"].AsString(),
                    Identifier = infoRoot["GUID"].AsString(),
                    AspectRatio = infoRoot["Aspect Ratio"].AsFloat() ?? 0.0f,
                    Rating = infoRoot["Rating"].AsInteger() ?? 0,
                    Date = Util.ReadImageTimestamp(infoRoot["DateAsTimerInterval"].AsFloat() ?? 0.0f),
                    ModifiedDate = Util.ReadImageTimestamp(infoRoot["ModDateAsTimerInterval"].AsFloat() ?? 0.0f),
                    MetadataModifiedData = Util.ReadImageTimestamp(infoRoot["MetaModDateAsTimerInterval"].AsFloat() ?? 0.0f),
                    ImagePath = infoRoot["ImagePath"].AsString(),
                    ThumbnailImagePath = infoRoot["ThumbPath"].AsString()
                };

                IList faces = (IList)infoRoot["Faces"];
                if (faces != null) {
                    foreach (IDictionary faceDict in faces) {
                        FaceReference reference = new FaceReference() {
                            Index = faceDict["face index"].AsInteger() ?? 0,
                            FaceKey = faceDict["face key"].AsString()
                        };

                        string rectString = faceDict["rectangle"].AsString();

                        if (rectString != null) {
                            float[] points = rectString
                                .Replace("{", string.Empty)
                                .Replace("}", string.Empty)
                                .Split(',')
                                .Select(i => i.AsFloat().Value)
                                .ToArray();
                            reference.Rectangle = new FaceRect() {
                                X = points[0],
                                Y = points[1],
                                Width = points[2],
                                Height = points[3]
                            };
                        }

                        image.Faces.Add(reference);
                    }
                }

                this.Images.Add(image);
            }

            // Read faces list.
            IDictionary facesRoot = (IDictionary)root["List of Faces"];

            this.Faces.Clear();

            foreach (IDictionary infoRoot in facesRoot.Values) {
                Face face = new Face() {
                     Key = infoRoot["key"].AsString(),
                     Name = infoRoot["name"].AsString(),
                     KeyImageKey = infoRoot["key image"].AsString(),
                     KeyImageFaceIndex = infoRoot["key image face index"].AsInteger() ?? 0
                };

                this.Faces.Add(face);
            }
        }

    }
}
